/******************************************************************************
*
*   Filename    : toolbar.c
*   Author      : Ariff Ehsan
*   Date        : Oct. 27, 2009
*   Description : GUI Toolbar for Primer2.
*
******************************************************************************/

#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"

#include "toolbar.h"
#include "drtc.h"
#include "dlcd.h"
#include "dadc.h"

#include "util.h"

#define MAX_TEMP_COUNT 6

/******************************************************************************
*
*                            PROTOTYPE FUNCTIONS
*
******************************************************************************/

static void TOOLBAR_vTask( void * pvParameters );
void TOOLBAR_UpdateClock( void );
void TOOLBAR_UpdateBatt( void );
void TOOLBAR_DrawNumber( u8 x, u8 y, u8 num );
void TOOLBAR_UpdateTemp( void );

/******************************************************************************
*
*                            LOCAL VARIABLES
*
******************************************************************************/

xTaskHandle toolbar_xHandle;
xSemaphoreHandle toolbar_xSemaphore;

u16 toolbar_backColor;
u8  toolbar_tempCount;

extern u16  ADC_ConvertedValue[ADC_DMA_SIZE];

/******************************************************************************
*
*                            PUBLIC FUNCTIONS
*
******************************************************************************/

void TOOLBAR_Configuration( void )
    {
    toolbar_backColor = RGB_LIGHTBLUE;
    
    RTC_Configuration();
    ADC_Configuration();
    
    /* create toolbar task */
    xTaskCreate( TOOLBAR_vTask, ( signed portCHAR * ) "Toolbar",
                 configMINIMAL_STACK_SIZE, NULL, toolbar_TASK_PRIORITY, toolbar_xHandle );
    
    toolbar_xSemaphore = xSemaphoreCreateMutex();
    }

void TOOLBAR_GetResource( void )
    {
    xSemaphoreTake( toolbar_xSemaphore, ( portTickType ) portMAX_DELAY );
    }

void TOOLBAR_ReleaseResource( void )
    {
    xSemaphoreGive( toolbar_xSemaphore );
    }

void TOOLBAR_Refresh( void )
    {
    LCD_DrawFilledRect( 0, TOOLBAR_BOTTOM, 128, TOOLBAR_TOP-TOOLBAR_BOTTOM, toolbar_backColor );
    
    TOOLBAR_UpdateClock();
    TOOLBAR_UpdateBatt();
    
    toolbar_tempCount = MAX_TEMP_COUNT;
    TOOLBAR_UpdateTemp();
    }

/******************************************************************************
*
*                            PRIVATE FUNCTIONS
*
******************************************************************************/

static void TOOLBAR_vTask( void * pvParameters )
    {
    const portTickType xDelay10s = 10000 / portTICK_RATE_MS;
    portTickType xLastWakeTime = xTaskGetTickCount();
    
    TOOLBAR_GetResource();
    TOOLBAR_Refresh();
    TOOLBAR_ReleaseResource();
    
    while ( 1 )
        {
        vTaskDelayUntil( &xLastWakeTime, xDelay10s );
        
        TOOLBAR_GetResource();
        
        TOOLBAR_UpdateClock();
        TOOLBAR_UpdateBatt();
        TOOLBAR_UpdateTemp();
        
        TOOLBAR_ReleaseResource();
        }
    }

void TOOLBAR_UpdateClock( void )
    {
    u32 hh, mm, ss;
    
    RTC_GetTime( &hh, &mm, &ss );
    
    LCD_GetResource();
    
    u8 h24 = 0;
    if (hh > 12)
        {
        h24 = 1;
        hh -= 12;
        }
    
    if (hh == 0)
        hh = 12;
    
    u8 startPos = 2;
    
    LCD_DrawFilledRect( startPos, 145, CHAR_WIDTH*7, CHAR_HEIGHT, toolbar_backColor );
    LCD_SetTextColor( RGB_BLACK, toolbar_backColor );
    
    if (hh > 9)
        {
        LCD_PutChar( startPos, 145, '1' );
        startPos += CHAR_WIDTH;
        }
    
    hh %= 10;
    LCD_PutChar( startPos, 145, '0' + hh );
    startPos += CHAR_WIDTH;
    
    LCD_PutChar( startPos, 145, ':' );
    startPos += CHAR_WIDTH;
    
    u8 t = mm/10;
    LCD_PutChar( startPos, 145, '0' + t );
    startPos += CHAR_WIDTH;
    
    t = mm % 10;
    LCD_PutChar( startPos, 145, '0' + t );
    startPos += CHAR_WIDTH;
    
    if ( h24 == 0)
        LCD_PutChar( startPos, 145, 'a' );
    else
        LCD_PutChar( startPos, 145, 'p' );
    
    startPos += CHAR_WIDTH;
    LCD_PutChar( startPos, 145, 'm' );
    
    LCD_ReleaseResource();
    }

void TOOLBAR_UpdateBatt( void )
    {
    LCD_GetResource();
    
    LCD_DrawRect( 117, TOOLBAR_BOTTOM+4, 7, 1, RGB_BLACK );
    LCD_DrawRect( 117, TOOLBAR_BOTTOM+4, 1, 20, RGB_BLACK );
    LCD_DrawRect( 123, TOOLBAR_BOTTOM+4, 1, 20, RGB_BLACK );
    LCD_DrawRect( 117, TOOLBAR_BOTTOM+24, 7, 1, RGB_BLACK );
    LCD_DrawRect( 119, TOOLBAR_BOTTOM+25, 3, 1, RGB_BLACK );

    s16 VBat = -1;
    u16 vbat;
    volatile int i;

    // Measure VBAT
    //    vbat = ADC_ConvertedValue[0];  //*( (u16*)ADC1_DR_Address );      // <=== note changed

    // Calculate the mean value       // YRT 20081023
    vbat = 0;
    for ( i = 0; i < ADC_NB_SAMPLES; i++)
        {
        vbat += ADC_ConvertedValue[0 + i*ADC_NB_CHANNELS];
        }
    vbat = vbat / ADC_NB_SAMPLES;

    vbat = vbat & 0xFFF;
    vbat = ( vbat * VDD_VOLTAGE_MV ) / 0x1000;

    vbat *= 2; //Divider bridge  Vbat <-> 1M -<--|-->- 1M <-> Gnd,

    if ( VBat == -1)
        {
        VBat = vbat;
        }
    else
        {
        VBat = (VBat>>1) + (vbat>>1);
        }
    
    u16 v = VBat;
    u8 startPos = 2;
    
    v = VBat;
    
    if (v > BAT_FULL_VOLTAGE)
        v = BAT_FULL_VOLTAGE;
    else if ( v < NO_BAT_VOLTAGE )
        v = NO_BAT_VOLTAGE;
    
    v = v - NO_BAT_VOLTAGE;
    
    v = v / 120;
    v -= 1;
    
    if (v < 0)
        v = 0;
    else if (v > 10)
        v = 10;
    
    startPos = 6;
    
    for (i = 0; i < v; i++)
        {
        LCD_DrawRect( 119, TOOLBAR_BOTTOM+startPos, 3, 1, RGB_BLACK );
        startPos += 2;
        }
    
    /*startPos = 2;
    u8 str[6];
    u8 len;
    v = VBat;
    
    UTIL_IntToStr( str, &len, v );
    
    if (len > 0)
        {
        for (i = 0; i < len; i++)
            {
            LCD_PutChar( startPos, 2, str[i] );
            startPos += CHAR_WIDTH;
            }
        }
    else
        {
        LCD_DrawFilledRect( 2, 40, 10, 10, RGB_RED );
        }*/
    
    LCD_ReleaseResource();
    }

void TOOLBAR_UpdateTemp( void )
    {
    if (++toolbar_tempCount <= MAX_TEMP_COUNT)
        return;
    
    toolbar_tempCount = 0;
    
    s32 temp;
    volatile int i;

    // Measure temp
    //    s16 *p=&ADC_ConvertedValue[1];     // intent; point to first of x results from same source - use a short name for it!
    // will not help reduce mains ripple because conversions are SO FAST!!
    // Calculate the mean value
    //    temp = (p[0]+p[1]+p[2]+p[3])/4;    // take avg of burst of 4 temp reads. may only help reject hi freq noise a bit
    // YRT 20081023 : add touchsreen adc channels for Primer2, buffer managed by DMA

    // Calculate the mean value
    temp = 0;
    for ( i = 0; i < ADC_NB_SAMPLES; i++)
        {
        temp += ADC_ConvertedValue[1 + i*ADC_NB_CHANNELS];
        }
    temp = temp / ADC_NB_SAMPLES;

    temp = temp & 0xFFF;
    temp = ( temp * VDD_VOLTAGE_MV ) / 0x1000;  //finds mV
    temp = (((1400-temp)*100000)/448)+25000;    //gives approx temp x 1000 degrees C

    //Fahrenheit = 32 + 9 / 5 * Celsius
#ifdef PRIMER2_FAHRENHEIT
    temp = 32000 + (9 * temp) / 5 ;
#endif

    temp = temp / 100;
    u16 T = temp;
    
    LCD_GetResource();
    
    LCD_DrawFilledRect( 2, TOOLBAR_BOTTOM+2, CHAR_WIDTH*6, CHAR_HEIGHT, toolbar_backColor );
    LCD_SetTextColor( RGB_BLACK, toolbar_backColor );
    
    u8 startPos = 2;
    
    u16 t = T/100;
    LCD_PutChar( startPos, TOOLBAR_BOTTOM+2, '0'+t );
    startPos += CHAR_WIDTH;
    
    T = T % 100;
    t = T/10;
    LCD_PutChar( startPos, TOOLBAR_BOTTOM+2, '0'+t );
    startPos += CHAR_WIDTH;
    
    LCD_PutChar( startPos, TOOLBAR_BOTTOM+2, '.' );
    startPos += CHAR_WIDTH;
    
    t = T % 10;
    LCD_PutChar( startPos, TOOLBAR_BOTTOM+2, '0'+t );
    startPos += CHAR_WIDTH;
    
    LCD_PutChar( startPos, TOOLBAR_BOTTOM+2, '`' );
    startPos += CHAR_WIDTH;
    
    LCD_PutChar( startPos, TOOLBAR_BOTTOM+2, 'c' );
    startPos += CHAR_WIDTH;
    
    /*startPos = 2;
    u8 str[6];
    u8 len;
    T = temp;
    
    UTIL_IntToStr( str, &len, T );
    
    if (len > 0)
        {
        for (i = 0; i < len; i++)
            {
            LCD_PutChar( startPos, 2, str[i] );
            startPos += CHAR_WIDTH;
            }
        }
    else
        {
        LCD_DrawFilledRect( 2, 40, 10, 10, RGB_RED );
        }*/
    
    LCD_ReleaseResource();
    }

void TOOLBAR_DrawNumber( u8 x, u8 y, u8 num )
    {
    
    /*
      7  -
      5 | | 6
      4  -
      2 | | 3
      1  -
    */
    
    //1
    if ( num == 2 || num == 3 || num == 5 || num == 6 || num == 8 || num == 9 || num == 0 )
        {
        LCD_DrawFilledRect( x+1, y, 3, 1, RGB_WHITE );
        LCD_DrawFilledRect( x+2, y+1, 1, 1, RGB_WHITE );
        }
    
    //2
    if ( num == 2 || num == 6 || num == 8 || num == 0 )
        {
        LCD_DrawFilledRect( x, y+1, 1, 10, RGB_WHITE );
        LCD_DrawFilledRect( x+1, y+2, 1, 8, RGB_WHITE );
        }
    
    //3
    if ( num == 1 || num == 3 || num == 4 || num == 5 || num == 6 || num == 7 || num == 8 || num == 9 || num == 0 )
        {
        LCD_DrawFilledRect( x+3, y+2, 1, 8, RGB_WHITE );
        LCD_DrawFilledRect( x+4, y+1, 1, 10, RGB_WHITE );
        }
    
    //4
    if ( num == 2 || num == 3 || num == 4 || num == 5 || num == 6 || num == 8 || num == 9 )
        {
        LCD_DrawFilledRect( x+1, y+11, 3, 1, RGB_WHITE );
        LCD_DrawFilledRect( x+1, y+12, 3, 1, RGB_WHITE );
        }
    
    //5
    if ( num == 4 || num == 5 || num == 6 || num == 8 || num == 9 || num == 0 )
        {
        LCD_DrawFilledRect( x, y+13, 1, 9, RGB_WHITE );
        LCD_DrawFilledRect( x+1, y+14, 1, 7, RGB_WHITE );
        }
    
    //6
    if ( num == 1 || num == 2 || num == 3 || num == 4 || num == 7 || num == 8 || num == 9 || num == 0 )
        {
        LCD_DrawFilledRect( x+3, y+14, 1, 7, RGB_WHITE );
        LCD_DrawFilledRect( x+4, y+13, 1, 9, RGB_WHITE );
        }
    
    //7
    if ( num == 2 || num == 3 || num == 5 || num == 6 || num == 7 || num == 8 || num == 9 || num == 0)
        {
        LCD_DrawFilledRect( x+2, y+21, 1, 1, RGB_WHITE );
        LCD_DrawFilledRect( x+1, y+22, 3, 1, RGB_WHITE );
        }
    
    }

